import { filterRoutes, resetRouter, router } from '@/router'
import store from '@/store'
import Vue from 'vue'

// 枚举交互事件类型
export const EventType = {
  INIT: 'init',
  ROUTER: 'router',
  STATIS: 'statis'
}

/**
 * @description 子应用启动监听入口
 */
export function startMicroApp () {
  if (!isMicroApp()) return
  // 初始化数据监听
  addListener(initListener, true)
  // 装载路由监听
  addListener(routerListener)
  // 注册真实 window （在vue文件内可直接使用 this.__window__ 代替）
  Vue.prototype.__window__ = useWindow()
}

/**
 * @description 添加事件监听
 */
export function addListener (dataListener, autoTrigger) {
  window.microApp.addDataListener(dataListener, autoTrigger)
}

/**
 * @description 初始化数据监听
 */
export async function initListener ({ data, type }) {
  if (type === EventType.INIT) {
    try {
      console.log('=====INIT DATA=====', data)
      store.dispatch('Login', data)
      let menu = data.menu
      const config = await import('@/router/routeConfig.js')
      menu = menu.concat(config.default.map(r => ({ ...r, pidsByPath: true })))
      const routes = filterRoutes(menu).reduce((pre, cur) => {
        return pre.concat(cur)
      }, [])
      resetRouter()
      router.addRoutes(routes)
      if (data.path) {
        router.push({
          path: data.path,
          query: data.query
        })
      }
    } catch (error) {
      console.error('micro init error!')
    }
  }
}

/**
 * @description 路由监听
 */
export function routerListener (state) {
  if (state && state.type === EventType.ROUTER) {
    try {
      const { api, route } = state.data
      router[api](route)
    } catch (error) {
      console.error(error.message)
    }
  }
}

/**
 * @description 发送数据给主应用
 */
export function sendMicroData (type, data = {}) {
  if (!isMicroApp()) return
  window.microApp.dispatch({ type, data })
}

/**
 * @description 是否在微前端环境中
 */
export function isMicroApp () {
  return window.__MICRO_APP_ENVIRONMENT__
}

/**
 * @description use window（子应用window对象被 micro-app变异为代理，需要替换为 window.rawWindow）
 */
export function useWindow () {
  return isMicroApp() ? window.rawWindow : window
}
